import editorStyle from '../style/default-style';
import G6, {Graph, IGroup, IShape, ModelConfig} from '@antv/g6';
import {Item} from '@antv/g6-core/lib/types';
import NodeStateType from '../consts/node-state-type';
import NodeAttrField from '../consts/node-attr-field';
import {IElement} from '@antv/g-base/src/interfaces';
import anchorStyle from '../def/anchor-style';
import StateType from '../consts/state-type';

const endDefaultOptions = {
    icon: null,
    iconStyle: {
        width: 18,
        height: 18,
        left: 6,
        top: 6,
    },
    style: {
        ...editorStyle.nodeStyle,
        fill: '#ffcdd2',
        stroke: '#f44336',
        cursor: 'default',
    },
    stateStyles: {
        selected: {
            fill: '#ef9a9a',
        },
        hover: {
            cursor: editorStyle.cursor.hoverNode,
        }
    },
    anchorStyle: {
        normalStyle: {
            ...anchorStyle.normalStyle,
            fill: '#fff',
            stroke: '#f5857d',
        },
        hideStyle: {
            ...anchorStyle.hideStyle,
            fill: '#fff',
        },
        showStyle: {
            ...anchorStyle.showStyle,
            fill: '#fff',
        },
        focusStyle: {
            ...anchorStyle.focusStyle,
            fill: '#f8c7c4',
        },
        nearStyle: {
            ...anchorStyle.nearStyle,
            fill: '#faa9a3',
        },
        boldStyle: {
            ...anchorStyle.boldStyle,
            fill: '#fcdddb',
            stroke: '#faa9a3',
        },
        thinStyle: {
            ...anchorStyle.thinStyle,
            fill: '#fff',
            stroke: '#f5857d',
        }
    },
    selectboxStyle: {
        radius: 0,
        stroke: '#aaaaaa',
        lineWidth: 1,
        lineDash:  [2, 2],
    }
};

export default function () {

    G6.registerNode('end-event', {
        shapeType: 'circle',
        labelPosition: 'bottom',
        options: {
            ...endDefaultOptions
        },
        getShapeStyle(cfg: ModelConfig) {
            cfg.size = [30, 30];
            const width = cfg.size[0];
            return {
                x: 0,
                y: 0,
                r: width / 2,
                ...endDefaultOptions.style,
            };
        },
        /**
         * 绘制节点，包含文本
         * @param  {Object} cfg 节点的配置项
         * @param  {G.Group} group 图形分组，节点中的图形对象的容器
         * @return {G.Shape} 绘制的图形，通过 node.get('keyShape') 可以获取到
         */
        draw(cfg: ModelConfig | undefined, group: IGroup | undefined): IShape {
            const shape = group?.addShape('circle', {
                draggable: true,
                attrs: {
                    ...endDefaultOptions.style,
                    x: 0,
                    y: 0,
                    r: 20,
                    // lineWidth: 1,
                    // cursor: 'move',
                    lineDash: /^ghost/.test(cfg?.id as string) ? [5, 5] : [0, 0],
                    opacity: /^ghost/.test(cfg?.id as string) ? 0.5 : 1,
                    '$isMain': true,
                }
            });

            // shape?.toFront();
            return shape as IShape;
        },
        /**
         * 绘制后的附加操作，默认没有任何操作
         * @param  {Object} cfg 节点的配置项
         * @param  {G.Group} group 图形分组，节点中的图形对象的容器
         */
        afterDraw(cfg: ModelConfig | undefined, group: IGroup | undefined) {
            group?.addShape('path', {
                attrs: {
                    path: [
                        ['M', -6, -6],
                        ['L', 6, -6],
                        ['L', 6, 6],
                        ['L', -6, 6],
                        ['Z'] // close
                    ],
                    fill: endDefaultOptions.style.stroke,
                    stroke: endDefaultOptions.style.stroke,
                    cursor: 'move',
                    opacity: cfg?.id === 'ghost' ? 0.5 : 1
                },
                draggable: true,
            });

            // @ts-ignore
            this.drawAnchor(group);
        },
        getAnchorPoints() {
            return [
                [0.5, 0], // top
                [1, 0.5], // right
                [0.5, 1], // bottom
                [0, 0.5], // left
            ];
        },
        drawAnchor(group: IGroup | undefined) {
            // @ts-ignore
            // const group = node.getContainer();
            const bbox = group?.get('children')[0].getBBox();
            // @ts-ignore
            const {width, height, minX, minY} = bbox;
            // @ts-ignore
            const anchorPoints = this.getAnchorPoints();
            anchorPoints.forEach((p: number[], index: number) => {
                const anchor = group?.addShape('marker', {
                    attrs: {
                        ...endDefaultOptions.anchorStyle.normalStyle,
                        x: minX + width * p[0],
                        y: minY + height * p[1],
                        r: 4,
                        // fill: '#fff',
                        // stroke: '#64b5f6',
                        cursor: 'crosshair',
                        opacity: 0,
                        '$isAnchor': true,
                        '$anchorIndex': index
                    },
                    draggable: true,
                    capture: true
                });

                if (anchor) {
                    anchor.toFront();
                }
            });
        },
        /**
         * 设置节点的状态，主要是交互状态，业务状态请在 draw 方法中实现
         * 单图形的节点仅考虑 selected、active 状态，有其他状态需求的用户自己复写这个方法
         * @param  {String} name 状态名称
         * @param  {Object} value 状态值
         * @param  {Node} node 节点
         */
        setState(name: string | undefined, value: string | boolean | undefined, node: Item | undefined) {
            if (!node) {
                return ;
            }
            if (name === StateType.SELECTED) {
                const group = node?.getContainer();

                const existSelectBox = group?.find((item: IShape) => item.attr(NodeAttrField.SELECTBOX_IS_SELECTBOX)) as IElement;
                if (value) {
                    if (existSelectBox) {
                        return ;
                    }
                    const shape = group?.addShape('rect', {
                        draggable: false,
                        attrs: {
                            ...endDefaultOptions.selectboxStyle,
                            x: -(node.getBBox().width - 1 + 10) / 2,
                            y: -(node.getBBox().height - 1 + 10) / 2,
                            width: node.getBBox().width - 1 + 10,
                            height: node.getBBox().height - 1 + 10,
                            '$isSelectBox': true
                        }
                    });
                } else {
                    group?.removeChild(existSelectBox);
                }
            } else if (name === NodeStateType.NODE_ANCHOR_VISIBLE) {
                if (value) {
                    const group = node?.getContainer();
                    const anchorElements = group?.getChildren().filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR));
                    anchorElements?.forEach(item => {
                        item.attr(endDefaultOptions.anchorStyle.showStyle);
                    });
                } else {
                    const group = node?.getContainer();
                    const anchorElements = group?.getChildren().filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR));
                    anchorElements?.forEach(item => {
                        item.attr(endDefaultOptions.anchorStyle.hideStyle);
                    });
                }
            } else if (name === NodeStateType.NODE_ANCHOR_BOLD) {
                if (value) {
                    node?.getContainer().getChildren()
                        .filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR))
                        .forEach(item => item.attr(endDefaultOptions.anchorStyle.boldStyle));
                } else {
                    node?.getContainer().getChildren()
                        .filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR))
                        .forEach(item => item.attr(endDefaultOptions.anchorStyle.thinStyle));
                }
            } else if (name === NodeStateType.NODE_ANCHOR_FOCUS) {
                const group = node?.getContainer();
                const anchorElements = group?.getChildren().filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR));
                anchorElements?.forEach(item => item.attr(endDefaultOptions.anchorStyle.showStyle));
                const targetAnchorElement = anchorElements?.find(item => item.attr(NodeAttrField.ANCHOR_ANCHOR_INDEX) === value);
                targetAnchorElement?.attr(endDefaultOptions.anchorStyle.focusStyle);
            } else if (name === NodeStateType.NODE_ANCHOR_NEAR) {
                const group = node?.getContainer();
                const anchorElements = group?.getChildren().filter(item => item.attr(NodeAttrField.ANCHOR_IS_ANCHOR));
                anchorElements?.forEach(item => item.attr(endDefaultOptions.anchorStyle.boldStyle));
                const targetAnchorElement = anchorElements?.find(item => item.attr(NodeAttrField.ANCHOR_ANCHOR_INDEX) === value);
                targetAnchorElement?.attr(endDefaultOptions.anchorStyle.nearStyle);
            }
        },
    });
}
